
use anyhow::Result;
use hyper::{Request, Response, Client, body};
use hyper::client::HttpConnector;
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use std::borrow::Borrow;

use crate::miner::{JsonRpcResponse, JsonRpcError, SectorId};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct SectorStatus {
    #[serde(rename(deserialize = "SectorID"))]
    pub sector_id: u64,
    pub state: String,
}

//
// {
// 	"jsonrpc": "2.0",
// 	"method": "Filecoin.WorkerJobs",
// 	"params": [2, false],
// 	"id": 1
// }
//
// {
//     "jsonrpc": "2.0",
//     "result": {
//         "SectorID": 0,
//         "State": "Proving",
//         "CommD": {
//             "/": "baga6ea4seaqh3c4shbocpwncy2tnzxo7j3ab7uvqduchbii7fehgj35phlmhmfy"
//         },
//         "CommR": {
//             "/": "bagboea4b5abcbp76zkcklc7cjyetu5ry76c2qkrmd7x5ithmfyspsqhabkbr57sf"
//         },
//         "Proof": null,
//         "Deals": [
//             0
//         ],
//         "Ticket": {
//             "Value": null,
//             "Epoch": 0
//         },
//         "Seed": {
//             "Value": null,
//             "Epoch": 0
//         },
//         "PreCommitMsg": null,
//         "CommitMsg": null,
//         "Retries": 0,
//         "ToUpgrade": false,
//         "LastErr": "",
//         "Log": [],
//         "SealProof": 0,
//         "Activation": 0,
//         "Expiration": 0,
//         "DealWeight": "0",
//         "VerifiedDealWeight": "0",
//         "InitialPledge": "0",
//         "OnTime": 0,
//         "Early": 0
//     },
//     "id": 1
// }
///
pub async fn query_sector_status(client: &Client<HttpConnector>, url: &str, token: &str, sector: u64) -> Result<JsonRpcResponse<SectorStatus>>{
    let body = serde_json::json!({
        "jsonrpc": "2.0",
	    "method": "Filecoin.SectorsStatus",
	    "params": [sector, false],
	    "id": 1
    });
    let auth = format!("Bearer {}", token);
    let body = body::Body::from(body.to_string());

    let request = Request::builder()
        .uri(url)
        .header("Authorization", auth)
        .body(body)?;

    let rsp = client.request(request).await?;
    if rsp.status().is_success() {
        let buf = body::to_bytes(rsp).await?;
        let result: JsonRpcResponse<SectorStatus> = serde_json::from_slice(buf.borrow())?;
        Ok(result)
    } else {
        Err(anyhow::Error::msg(format!("http request got error response {}", rsp.status())))
    }
}

pub async fn query_sector_list(client: &Client<HttpConnector>, url: &str, token: &str, states: Option<Vec<&str>>) -> Result<JsonRpcResponse<Vec<u64>>> {
    let body = if states.is_none() {
        serde_json::json!({
                "jsonrpc": "2.0",
                "method": "Filecoin.SectorsListInStates",
                "params": [],
                "id": 1,
            })
    } else {
        let param = states.unwrap();
        if param.is_empty(){
            serde_json::json!({
                "jsonrpc": "2.0",
                "method": "Filecoin.SectorsListInStates",
                "params": [],
                "id": 1,
            })
        } else {
            serde_json::json!({
                "jsonrpc": "2.0",
                "method": "Filecoin.SectorsListInStates",
                "params": [param],
                "id": 1,
            })
        }
    };

    let auth = format!("Bearer {}", token);
    let body = body::Body::from(body.to_string());

    let request = Request::builder()
        .uri(url)
        .header("Authorization", auth)
        .body(body)?;

    let rsp = client.request(request).await?;
    if rsp.status().is_success() {
        let buf = body::to_bytes(rsp).await?;
        let result: JsonRpcResponse<Vec<u64>> = serde_json::from_slice(buf.borrow())?;
        Ok(result)
    } else {
        Err(anyhow::Error::msg(format!("http request got error response {}", rsp.status())))
    }
}